# 给定一个链表，返回链表开始入环的第一个节点。 如果链表无环，则返回 null。 
# 
#  为了表示给定链表中的环，我们使用整数 pos 来表示链表尾连接到链表中的位置（索引从 0 开始）。 如果 pos 是 -1，则在该链表中没有环。注意，po
# s 仅仅是用于标识环的情况，并不会作为参数传递到函数中。 
# 
#  说明：不允许修改给定的链表。 
# 
#  进阶： 
# 
#  
#  你是否可以使用 O(1) 空间解决此题？ 
#  
# 
#  
# 
#  示例 1： 
# 
#  
# 
#  
# 输入：head = [3,2,0,-4], pos = 1
# 输出：返回索引为 1 的链表节点
# 解释：链表中有一个环，其尾部连接到第二个节点。
#  
# 
#  示例 2： 
# 
#  
# 
#  
# 输入：head = [1,2], pos = 0
# 输出：返回索引为 0 的链表节点
# 解释：链表中有一个环，其尾部连接到第一个节点。
#  
# 
#  示例 3： 
# 
#  
# 
#  
# 输入：head = [1], pos = -1
# 输出：返回 null
# 解释：链表中没有环。
#  
# 
#  
# 
#  提示： 
# 
#  
#  链表中节点的数目范围在范围 [0, 104] 内 
#  -105 <= Node.val <= 105 
#  pos 的值为 -1 或者链表中的一个有效索引 
#  
#  Related Topics 哈希表 链表 双指针 
#  👍 1212 👎 0


from typing import List


class ListNode:
    def __init__(self, val, next=None):
        self.val = val
        self.next = next


# leetcode submit region begin(Prohibit modification and deletion)
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        if head is None:
            return None
        fast, slow = head, head
        while fast:
            slow = slow.next
            if fast.next is None:
                return None
            else:
                fast = fast.next.next
            if slow == fast:
                prev = head
                while prev != slow:
                    prev = prev.next
                    slow = slow.next
                return prev
        return None



# leetcode submit region end(Prohibit modification and deletion)


def log(*args, **kwargs):
    print(*args, **kwargs)


"""
哈希表: 将节点存在哈希表中判断重复  
"""
"""
快慢指针: 快慢相遇时, 慢到入环点的距离 == 起始点到入环点距离
"""
# 哈希表
# 遍历链表, 遇到重复节点返回, 否则无环
#     def detectCycle(self, head: ListNode) -> ListNode:
#         d = set()
#         node = head
#         i = 0
#         while node:
#             if node in d:
#                 return node
#             else:
#                 d.add(node)
#             node = node.next
#         return None
# 快慢指针, 快指针2, 慢指针1
# 快慢指针相遇时, fast走过n圈 a+n(b+c)+b=a+(n+1)b+nc
# 快指针走过是慢指针的两倍 故 a+(n+1)b+nc = 2 * (a + b), 即 a = (n-1)(b + c) + c
# 即 相遇点到入环点的距离 + n-1圈长 等于 链表头到入环点
# 相遇后再出发一个指针, 最终在入环点相遇

# def detectCycle(self, head: ListNode) -> ListNode:
#     if head is None:
#         return None
#     fast, slow = head, head
#     while fast:
#         slow = slow.next
#         if fast.next is None:
#             return None
#         else:
#             fast = fast.next.next
#         if fast == slow:
#             prev = head
#             while prev != slow:
#                 prev = prev.next
#                 slow = slow.next
#             return prev
#     return None
if __name__ == '__main__':
    s = Solution()
    # head = [3,2,0,-4], pos = 1
    h1 = ListNode(3)
    c1 = ListNode(2)
    n1 = ListNode(0)
    n2 = ListNode(-4)
    h1.next = c1
    c1.next = n1
    n1.next = n2
    n2.next = c1
    r1 = s.detectCycle(h1)
    assert r1 == c1, r1
